﻿/* Copyright 2010 Igor Francé
 * 
 * This file is part of ECMADoc (http://ecmadoc.codeplex.com).
 * 
 * ECMADoc is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * ECMADoc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with ECMADoc. 
 * If not, see http://www.gnu.org/licenses/.
 */
namespace EcmaDoc.Core.Items
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;

	/// <summary>
	/// Gets the collection of member dictionaries, organized by member <see cref="Visibility"/>.
	/// </summary>
	public class MemberCollection : Dictionary<Visibility, MemberDictionary>
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="MemberCollection"/> class.
		/// </summary>
		public MemberCollection()
		{
			this.Add(Visibility.Instance, new MemberDictionary());
			this.Add(Visibility.Prototype, new MemberDictionary());
			this.Add(Visibility.Public, new MemberDictionary());
			this.Add(Visibility.Private, new MemberDictionary());
			this.Add(Visibility.Static, new MemberDictionary());
		}

		/// <summary>
		/// Gets the public members of this collection.
		/// </summary>
		public MemberDictionary Public
		{
			get { return this[Visibility.Public]; }
		}

		/// <summary>
		/// Gets the instance members of this collection.
		/// </summary>
		public MemberDictionary Instance
		{
			get { return this[Visibility.Instance]; }
		}

		/// <summary>
		/// Gets the prototype members of this collection.
		/// </summary>
		public MemberDictionary Prototype
		{
			get { return this[Visibility.Prototype]; }
		}

		/// <summary>
		/// Gets the private members of this collection.
		/// </summary>
		public MemberDictionary Private
		{
			get { return this[Visibility.Private]; }
		}

		/// <summary>
		/// Gets the static members of this collection.
		/// </summary>
		public MemberDictionary Static
		{
			get { return this[Visibility.Static]; }
		}

		/// <summary>
		/// Gets the total count of top level members in all <see cref="MemberDictionary"/> groups of the current 
		/// instance.
		/// </summary>
		public int MemberCount
		{
			get
			{
				return this.Values.Sum(dict => dict.Count);
			}
		}

		/// <summary>
		/// Gets the total count of all members (counting recursively into all children) in all 
		/// <see cref="MemberDictionary"/> groups of the current instance.
		/// </summary>
		public int MemberCountRecursive
		{
			get
			{
				return this.Values.Sum(dict => dict.MemberCountRecursive);
			}
		}

		/// <summary>
		/// Gets all members in all visibility slots in this collection.
		/// </summary>
		public List<CodeItem> Members
		{
			get
			{
				List<CodeItem> result = new List<CodeItem>();
				foreach (MemberDictionary dict in this.Values)
					result.AddRange(dict.Values);

				return result;
			}
		}

		/// <summary>
		/// Gets all members in all visibility slots in this collection, collecting recursively from all children.
		/// </summary>
		public List<CodeItem> MembersRecursive
		{
			get
			{
				List<CodeItem> all = new List<CodeItem>();
				foreach (MemberDictionary dict in this.Values)
					all.AddRange(dict.MembersRecursive);

				return all;
			}
		}

		/// <summary>
		/// Returns a <see cref="String"/> that represents this instance.
		/// </summary>
		/// <returns>
		/// A <see cref="String"/> that represents this instance.
		/// </returns>
		public override string ToString()
		{
			string self = string.Empty;
			int total = 0;
			foreach (Visibility key in this.Keys)
			{
				if (this[key].Count == 0)
					continue;
				
				total += this[key].Count;
				self += self != string.Empty ? ", " : ": ";
				self += string.Format("{0}={1}", key, this[key].Count);
			}

			return string.Format("Count={0} {1}", total, self);
		}
	}
}
